home *** CD-ROM | disk | FTP | other *** search
Text File | 1988-05-28 | 3.6 KB | 95 lines | [TEXT/CCL ] |
- ; Ted Kaehler and Dave Patterson: a taste of SmallTalk
- ; W. W. Norton ed., chapter 5, pp. 65 ff.
- ; translated in Allegro Common Lisp by Jean-Pascal J. LANGE.
- ; © Copyright 1988 Jean-Pascal J. LANGE.
-
- (proclaim '(optimize (speed 3)
- (space 0)
- (safety 0)
- (compilation-speed 0) ))
-
- (defStruct HanoiDisk
- ; Each disk in the game is represented by an object of structure
- ; HanoiDisk. It has
- ; name: name of this disk (a character),
- ; width: size of the disk (1 is the smallest disk width),
- ; pole: number telling which pole the disk is on,
- ; diskRectangle: a rectangle on the screen that the disk occupies.
- (name nil)
- (width nil)
- (pole nil)
- (diskRectangle nil) )
-
- ; access
-
- (deFun pole (thisDisk) ; return which pole this disk is on
- (HanoiDisk-pole thisDisk) )
-
- (deFun name (thisDisk) ; return the name of this disk
- (HanoiDisk-name thisDisk) )
-
- (deFun whichTowers (aTowerOfHanoi)
- ; There are three global variables shared across the whole game:
- ; *TheTowers*: the structure that represents the whole game and
- ; holds the stacks of disks,
- ; *Thickness*: the thickness of a disk in screen dots,
- ; *DiskGap*: the number of screen dots between disks in a stack.
- (declare (special *TheTowers* *Thickness* *DiskGap*))
- ; install the structure representing the towers
- (setq *TheTowers* aTowerOfHanoi)
- (setq *Thickness* 14) ; thickness of a disk in screen dots
- (setq *DiskGap* 2) ) ; distance between disks
-
- (deFun widthPole (thisDisk size whichPole)
- (declare (special *TheTowers* *Thickness* *DiskGap*))
- ; set the values for this disk
- (setf (HanoiDisk-width thisDisk) size)
- (setf (HanoiDisk-pole thisDisk) whichPole)
- ; compute the center of the disk on the screen
- (let* ((where)
- (window-size (ask (front-window) (window-size)))
- (window-height (point-v window-size))
- (window-width (point-h window-size))
- (x0 (floor window-width 6))
- (y0 (- window-height 11))
- (h-distance (floor window-width 3)) )
- (cond ((not (>= size 1000))
- ; a normal disk
- (setf (HanoiDisk-name thisDisk)
- (code-char (+ (char-code #\A) (1- size))) )
- (let ((y (- y0 (* (- (howMany *TheTowers*) size)
- (+ *Thickness* *DiskGap*) ))))
- (setq where (make-point x0 y)) ) )
- (t (setf (HanoiDisk-name thisDisk) 'm) ; a mock disk
- (setq where
- (make-point (- (* h-distance whichPole) x0)
- (+ y0 *Thickness* *DiskGap*) ) ) ) )
- ; create the rectangle, specify its size and locate its center
- (let ((extent (make-point (* size 14) *Thickness*)))
- (setf (HanoiDisk-diskRectangle thisDisk)
- (originExtent #@(0 0) extent)) )
- ; locate the rectangle center
- (setCenter (HanoiDisk-diskRectangle thisDisk) where)) )
-
- (deFun centerDisk (thisDisk)
- ; returns a point that is the current center of this disk
- (center (HanoiDisk-diskRectangle thisDisk)) )
-
- (deFun moveUpon (thisDisk destination)
- ; this disk just moved. Record the new pole and tell the user.
- (declare (special *Thickness* *DiskGap*))
- (setf (HanoiDisk-pole thisDisk) (pole destination))
- ; remove the old image
- (invert thisDisk)
- ; reposition
- (let ((point (make-point 0 (+ *Thickness* *DiskGap*))))
- (setCenter (HanoiDisk-diskRectangle thisDisk)
- (subtract-points (centerDisk destination) point )) )
- ; display the new one
- (invert thisDisk) )
-
- (deFun invert (thisDisk)
- ; shows a disk on the screen by turning white to black
- ; in a rectangular region
- (invertRect (HanoiDisk-diskRectangle thisDisk)) )
-